/*
 * @Author: 0x9DEFA478
 * @Date: 2025-08-02 20:46:03
 * @LastEditTime: 2025-09-17 23:44:14
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * 
 */
#include "HMakeLog.hpp"
#include <sstream>
#include <chrono>
#include "Utility/H_String.h"




static std::string GetProcessString(H::size allCount,H::size currentCount){
  char buffer[8];
  std::stringstream ss;
  float percent=(float)currentCount*100.0f/(float)allCount;

  int percent_i;

  if(currentCount<allCount){
    percent_i=(int)percent;
  }else{
    percent_i=100;
  }

  int processCount0=percent_i/2;
  int processCount1=percent_i%2;
  int processCount2=50-processCount1-processCount0;

  if(processCount0>0){
    ss<<std::string(processCount0,'=');
  }
  if(processCount1>0){
    ss<<'>';
  }
  if(processCount2>0){
    ss<<std::string(processCount2,'-');
  }

  auto len=H_StringPrintf((Hbyte*)buffer,8,"%.1f%%",percent);
  ss<<"["+std::string(buffer,0,len)+"  "+std::to_string(currentCount)+"/"+std::to_string(allCount)+"]";

  return ss.str();
}




namespace HMake{


  Log::Log(std::ostream& ostream)noexcept:fifo(1024),ostream(ostream),isStop(true),thread(nullptr),allCount(0),currentCount(0){}

  Log::~Log(){
    Stop();
  }

  void Log::WriteLog(const std::string& text,Type type){
    if(isStop.load()){
      return;
    }
    while(!fifo.Write(type,text)){
      fifo.WaitForWrite();
    }
  }

  void Log::ResetCount(H::size AllCount){
    currentCount=0;
    allCount=AllCount;
    skipCount=0;
    updateCount=0;
  }
  
  void Log::Start(){
    isStop.store(false);

    thread=new std::thread([this](){
      bool IsLock=false;
      bool reqStop=false;

      endString=GetProcessString(allCount,currentCount);

      ostreamLock.Lock();
      ostream<<std::endl<<endString;
      ostream.flush();
      ostreamLock.Unlock();

      for(;;){
        auto item=fifo.Read();

        if(!item.Valid){
          if(IsLock){
            IsLock=false;
            ostreamLock.Unlock();
          }
          emptyEvent.Trigger();
          //这里需要小心, 解锁ostreamLock后才能退出线程
          if(isStop.load(std::memory_order::consume)){
            if(reqStop){
              break;
            }
            reqStop=true;//请求结束后还需要查询一次FIFO 保证停止之前的所有消息都输出
          }
          fifo.WaitForRead(8);
          continue;
        }

        //保证在锁定状态下输出
        if(!IsLock){
          IsLock=true;
          ostreamLock.Lock();
        }

        bool TaskUpdate=false;

        switch(item.type){
          case Type::TaskDone:
            updateCount++;
          case Type::TaskDoneSkip:
            TaskUpdate=true;
            currentCount++;
            skipCount=currentCount-updateCount;
            endString=GetProcessString(allCount,currentCount);
            break;
          case Type::Default:
          default:
            break;
        }
        
        if(TaskUpdate||(item.text.length()>0)){
          if(item.text.length()>0){
            ostream<<"\r\e[2K"<<item.text;
            if(*item.text.rbegin()!='\n'){
              ostream<<std::endl;
            }
          }else{
            ostream<<"\r\e[2K";
          }
          ostream<<endString;
          ostream.flush();
        }

      }

      emptyEvent.Trigger();

    });
  }

  void Log::Stop(){
    if(thread!=nullptr){
      isStop.store(true);
      thread->join();
      delete thread;
      thread=nullptr;
    }
  }

  void Log::Lock()noexcept{
    while(!fifo.Empty()){
      emptyEvent.Acquire();
    }
    ostreamLock.Lock();
    ostream<<"\r\e[2K";//清除掉已经打印的进度条
    ostream.flush();
  }

  void Log::Unlock()noexcept{
    ostream<<std::endl;//补上可能缺失的回车后才解锁
    ostream.flush();
    ostreamLock.Unlock();
  }

}



